package com.castle.fortress.admin.exchange.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.exchange.dto.ExchangeConfigDto;
import com.castle.fortress.admin.exchange.entity.ExchangeConfigEntity;
import com.castle.fortress.admin.exchange.entity.ExchangeVoucherEntity;
import com.castle.fortress.admin.exchange.dto.ExchangeVoucherDto;
import com.castle.fortress.admin.exchange.enums.CodeTypeEnum;
import com.castle.fortress.admin.exchange.enums.VoucherStatusEnum;
import com.castle.fortress.admin.exchange.service.ExchangeConfigService;
import com.castle.fortress.admin.exchange.service.ExchangeVoucherService;
import com.castle.fortress.common.enums.DataPermissionPostEnum;
import com.castle.fortress.common.enums.YesNoEnum;
import com.castle.fortress.common.utils.ConvertUtil;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.enums.OperationTypeEnum;
import com.castle.fortress.admin.core.annotation.CastleLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.FileCopyUtils;
import springfox.documentation.annotations.ApiIgnore;
import org.apache.logging.log4j.util.Strings;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import com.castle.fortress.admin.utils.ExcelUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import com.castle.fortress.common.entity.DynamicExcelEntity;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 兑换券 控制器
 *
 * @author whc
 * @since 2022-12-06
 */
@Api(tags = "兑换券管理控制器")
@Controller
public class ExchangeVoucherController {
    @Autowired
    private ExchangeVoucherService exchangeVoucherService;

    @Autowired
    private ExchangeConfigService exchangeConfigService;

    /**
     * 兑换券的分页展示
     *
     * @param exchangeVoucherDto 兑换券实体类
     * @param current            当前页
     * @param size               每页记录数
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("兑换券分页展示")
    @GetMapping("/exchange/exchangeVoucher/page")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:pageList")
    public RespBody<IPage<ExchangeVoucherDto>> pageExchangeVoucher(ExchangeVoucherDto exchangeVoucherDto, @RequestParam(required = false) Integer current, @RequestParam(required = false) Integer size) {
        Integer pageIndex = current == null ? GlobalConstants.DEFAULT_PAGE_INDEX : current;
        Integer pageSize = size == null ? GlobalConstants.DEFAULT_PAGE_SIZE : size;
        Page<ExchangeVoucherDto> page = new Page(pageIndex, pageSize);
        IPage<ExchangeVoucherDto> pages = exchangeVoucherService.pageExchangeVoucherExtends(page, exchangeVoucherDto);

        return RespBody.data(pages);
    }

    /**
     * 兑换券的列表展示
     *
     * @param exchangeVoucherDto 兑换券实体类
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("兑换券列表展示")
    @GetMapping("/exchange/exchangeVoucher/list")
    @ResponseBody
    public RespBody<List<ExchangeVoucherDto>> listExchangeVoucher(ExchangeVoucherDto exchangeVoucherDto) {
        List<ExchangeVoucherDto> list = exchangeVoucherService.listExchangeVoucher(exchangeVoucherDto);
        return RespBody.data(list);
    }

    /**
     * 兑换券保存
     *
     * @param exchangeVoucherDto 兑换券实体类
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.INSERT)
    @ApiOperation("兑换券保存")
    @PostMapping("/exchange/exchangeVoucher/save")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:save")
    public RespBody<String> saveExchangeVoucher(@RequestBody ExchangeVoucherDto exchangeVoucherDto) {
        if (exchangeVoucherDto == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ExchangeVoucherEntity exchangeVoucherEntity = ConvertUtil.transformObj(exchangeVoucherDto, ExchangeVoucherEntity.class);
        if (exchangeVoucherService.save(exchangeVoucherEntity)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    @CastleLog(operLocation = "生成兑换券", operType = OperationTypeEnum.INSERT)
    @ApiOperation("生成兑换券")
    @PostMapping("/exchange/exchangeVoucher/generate")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:generate")
    public RespBody<String> generateExchangeVoucher(@RequestBody HashMap<String, String> params) {
        exchangeVoucherService.generate(params);
        return RespBody.success("操作成功");
    }

    /**
     * 兑换券编辑
     *
     * @param exchangeVoucherDto 兑换券实体类
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.UPDATE)
    @ApiOperation("兑换券编辑")
    @PostMapping("/exchange/exchangeVoucher/edit")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:edit")
    public RespBody<String> updateExchangeVoucher(@RequestBody ExchangeVoucherDto exchangeVoucherDto) {
        if (exchangeVoucherDto == null || exchangeVoucherDto.getId() == null || exchangeVoucherDto.getId().equals(0L)) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ExchangeVoucherEntity exchangeVoucherEntity = ConvertUtil.transformObj(exchangeVoucherDto, ExchangeVoucherEntity.class);
        if (exchangeVoucherService.updateById(exchangeVoucherEntity)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 兑换券删除
     *
     * @param id
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.DELETE)
    @ApiOperation("兑换券删除")
    @PostMapping("/exchange/exchangeVoucher/delete")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:delete")
    public RespBody<String> deleteExchangeVoucher(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (exchangeVoucherService.removeById(id)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 兑换券批量删除
     *
     * @param ids
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.DELETE)
    @ApiOperation("兑换券批量删除")
    @PostMapping("/exchange/exchangeVoucher/deleteBatch")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:deleteBatch")
    public RespBody<String> deleteExchangeVoucherBatch(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() < 1) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (exchangeVoucherService.removeByIds(ids)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 兑换券详情
     *
     * @param id 兑换券id
     * @return
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("兑换券详情")
    @GetMapping("/exchange/exchangeVoucher/info")
    @ResponseBody
    @RequiresPermissions("exchange:exchangeVoucher:info")
    public RespBody<ExchangeVoucherDto> infoExchangeVoucher(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ExchangeVoucherDto exchangeVoucherDto = exchangeVoucherService.getByIdExtends(id);

        return RespBody.data(exchangeVoucherDto);
    }

    /**
     * 动态表头导出 依据展示的字段导出对应报表
     *
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @CastleLog(operLocation = "兑换券", operType = OperationTypeEnum.EXPORT)
    @PostMapping("/exchange/exchangeVoucher/exportDynamic")
    @ApiOperation("动态表头导出，依据展示的字段导出对应报表")
    public void exportDynamic(@RequestBody DynamicExcelEntity<ExchangeVoucherDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
        List<ExchangeVoucherDto> list = exchangeVoucherService.listExchangeVoucher(dynamicExcelEntity.getDto());
        //字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
        List<List<Object>> dataList = null;
        Map<String, Map<String, Object>> convertMap = new HashMap<>();
        //枚举处理 selectEnum 字段使用枚举（DataPermissionPostEnum） 转义
        Map<String, Object> enumTranslateMap = new HashMap<>();
        for (CodeTypeEnum e : CodeTypeEnum.values()) {
            enumTranslateMap.put(e.getCode().toString(), e.getName());
        }
        convertMap.put("type", enumTranslateMap);

        Map<String, Object> statusMap = new HashMap<>();
        for (VoucherStatusEnum e : VoucherStatusEnum.values()) {
            statusMap.put(e.getCode().toString(), e.getName());
        }
        Map<String, Object> bindMap = new HashMap<>();
        for (YesNoEnum e : YesNoEnum.values()) {
            bindMap.put(e.getCode().toString(), e.getName());
        }
        convertMap.put("type", statusMap);
        convertMap.put("status", enumTranslateMap);
        convertMap.put("isBind", bindMap);
        dataList = ExcelUtils.convertToDataList(list, dynamicExcelEntity.getHeaderList(), convertMap, null);

        /**
         * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
         */
        ExcelUtils.exportDynamic(response, dynamicExcelEntity.getFileName() + ".xlsx", null, list, dynamicExcelEntity.getHeaderList(), dataList);
    }

    /**
     * 兑换券下载
     *
     * @param exchangeVoucherDto
     * @param response
     * @throws Exception
     */
    @CastleLog(operLocation = "兑换券下载", operType = OperationTypeEnum.EXPORT)
    @PostMapping("/exchange/exchangeVoucher/download")
    @ApiOperation("兑换券下载")
    @RequiresPermissions("exchange:exchangeVoucher:download")
    public void download(@RequestBody ExchangeVoucherDto exchangeVoucherDto, HttpServletResponse response) throws Exception {
        final ExchangeConfigEntity config = exchangeConfigService.getById(exchangeVoucherDto.getExchangeId());
        List<ExchangeVoucherDto> list = exchangeVoucherService.downloadList(exchangeVoucherDto);
        String tempDir = System.getProperty("java.io.tmpdir");
        String configId = config.getId().toString();
        final File folder = new File(tempDir + File.separatorChar + configId);
        //删除之前的 如果存在的话
        folder.delete();
        //创建新的
        folder.mkdirs();
        list.forEach(item -> {
            QrCodeUtil.generate("https://hutool.cn/", 300, 300, FileUtil.file(tempDir + File.separatorChar + configId + File.separatorChar + item.getId() + ".jpg"));
        });
        File zipFile = new File(tempDir + File.separatorChar + configId + ".zip");
        if (zipFile.exists()) {
            //如果存在 直接删除
            zipFile.delete();
        }
        ZipUtil.zip(tempDir + File.separatorChar + configId);
        folder.delete();//压缩完成后删除文件夹
        zipFile = new File(tempDir + File.separatorChar + configId + ".zip");
        final FileInputStream inputStream = new FileInputStream(zipFile);
//        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        String filename = zipFile.getName();
        response.setHeader("filename", filename);
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
        final ServletOutputStream outputStream = response.getOutputStream();
        FileCopyUtils.copy(inputStream, outputStream);
    }
}
